#include "pool.h"
#include "SafePtr.h"
#include <stdio.h>


class MyClass {
public:
	int a;
	char b;
	MyClass(int a, char b) {
		this->a = a;
		this->b = b;
	}
	MyClass() {
		a = 0;
		b = 'z';
	}
	SafePtrLibraryNewDeleteMacro(C);
};

/*
 * Code inspired by initial code from here: http://www.csc.villanova.edu/~mdamian/threads/posixsem.html
 */

void * ThreadAdd(void * a)
{       
    for ( int i = 0; i < 20; i++ )
    {
        cout << "iteration: " << i << endl << endl;
        SafePtr<MyClass> foo2(new MyClass(2,'a'));
    }
}

void testWithThreads()
{
    pthread_t tid1, tid2;

    if(pthread_create(&tid1, NULL, ThreadAdd, NULL))
    {
      printf("\n ERROR creating thread 1");
      exit(1);
    }
    
    if(pthread_create(&tid2, NULL, ThreadAdd, NULL))
    {
      printf("\n ERROR creating thread 2");
      exit(1);
    } 
      
    if(pthread_join(tid1, NULL))    /* wait for the thread 1 to finish */
    {
      printf("\n ERROR joining thread");
      exit(1);
    } 
      
    if(pthread_join(tid2, NULL))        /* wait for the thread 2 to finish */
    {   
      printf("\n ERROR joining thread");
      exit(1);
    }

}

int main() {
    cout << "Welcome and thank you for using SafePtr lib, the best pointer lib in";
    cout << " the know world!\n" ;

    cout << "We will first start by initializing our test class objects:\n";
    cout << "***********************************************************\n\n" ;
    cout << "Creating foo\n";
    cout << "Creating foo2\n";
    cout << "Creating foo3 an array of 5\n";
	SafePtr<MyClass> foo(new MyClass(2,'a'));
	SafePtr<MyClass> foo2(new MyClass(3,'a'));
	SafePtr<MyClass> foo3(new MyClass[5]);

	//foo3[0] = new MyClass(5, 'd');
	//foo3[1] = new MyClass(6, 'd');
	//foo3[2] = new MyClass(7, 'd');

    cout << "\n\nWe now illustrate some sample runs: \n" ;
    cout << "*********************************** \n" ;

	foo3[4].a = 10;
    cout << "Printing val of foo3[4]: ";
	cout << foo3[4].a << endl;


	SafePtr<MyClass> foo4;
    cout << "Printing val of foo->a:  ";
	cout << foo->a << endl;
    cout << "\nfoo4 is a copy of foo...(It will be allocated new memory)\n";
	foo4 = foo;
    cout << "Printing val of foo4->a:  ";
	cout << foo4->a << endl;

	foo4->a = 100;

    cout << "\nfoo4->a changed to 100\n";
    cout << "Printing val of foo->a:  ";
	cout << foo->a << endl;
    cout << "Printing val of foo4->a:  ";
	cout << foo4->a << endl;

    cout << "\n\nOur memory pool is protected against concurrency issues. We will now let 2 Threads compete to create and destroy 10 safe objects each:\n" ;
    cout << "*************************************************************************************************************************************** \n" ;
    cout <<"press any key when ready!!";
    char c;
    c = getchar();

    cout << globalPool << endl;

    testWithThreads();
	
    cout << "\n\nGarbage collection will now take place: \n" ;
    cout << "***************************************\n" ;
	return 0;
}
